/**
 ****************************************************************************************
 *
 * @file app_gatt.c
 *
 * @brief App SubTask of GATT Message - Example
 *
 * < If want to modify it, recommend to copy the file to 'user porject'/src >
 ****************************************************************************************
 */
#if (GATT_CLI)

#include "drvs.h"
#include "app.h"
#include "gatt.h"
#include "gatt_api.h"
#include "gapc_api.h"
#include "app_user.h"
#include "hid_desc.h"
/*
 * DEFINES
 ****************************************************************************************
 */
 #if (DBG_GATT)
#include "dbg.h"
#define DEBUG(format, ...)    debug("<%s,%d>" format "\r\n", __MODULE__, __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format, ...)
#define debugHex(dat, len)
#endif
 
enum os_judge_step
{
    STEP_NONE,
    STEP_INIT,
    STEP_DONE,
    STEP_NEXT,
};

struct os_judge_env
{
    uint8_t os_type;
    uint8_t step;
    uint8_t mtu;
    uint8_t step_tmp;
} os_judge_env;

const uint8_t apple_vendor_uuid[] = {0x66, 0x43, 0xAE, 0x10, 0x79, 0x48, 0xF8, 0xA5, 0x91, 0x45, 0xB4, 0xBB, 0x78, 0x1E, 0x61, 0xD0};


/*
 * MESSAGE HANDLERS
 ****************************************************************************************
 */
void os_judge_init(void)
{
    os_judge_env.os_type  = ANDROID;
    os_judge_env.step     = STEP_INIT;
    os_judge_env.step_tmp = STEP_NONE;
    
    g_master_os.os = 0xFF;
    g_master_os.read_report = 0xFF;
}

void os_judge_env_clr(void)
{
    os_judge_env.os_type  = ANDROID;
    os_judge_env.mtu      = 0;
    os_judge_env.step     = STEP_NONE;
    os_judge_env.step_tmp = STEP_NONE;
}

void os_judge_proc(void)
{ 
    if (os_judge_env.step == os_judge_env.step_tmp)
        return;
    
//    DEBUG("1step:%d, os_judeg:%d, os:%d", os_judge_env.step, g_master_os.read_report, g_master_os.os);
    
    os_judge_env.step_tmp  = os_judge_env.step;

    switch (os_judge_env.step)
    {
        case STEP_INIT:
        {
            DEBUG("STEP_INIT");
            os_judge_env.step = STEP_NEXT;
            gatt_disc(app_env.curidx, GATT_DISC_BY_UUID_SVC, 0x0001, 0xFFFF, 0x10, apple_vendor_uuid);
        } break;

        case STEP_DONE:
        {
            os_judge_env.step = STEP_NONE;
            g_master_os.os = os_judge_env.os_type;
            DEBUG("os:%d, %d",g_master_os.os, g_master_os.read_report);

            if (g_master_os.read_report == 1)
            {
                uint16_t length, handle;
                handle = hids_get_report_map_handle();
                const uint8_t *report_map = hid_get_report_map(g_master_os.os, &length);
                
                DEBUG("  Read REPORT_MAP(size:%d, 0x%02X)", length, handle);
                gatt_read_cfm(app_env.curidx, LE_SUCCESS, handle, length, report_map);
            }
            else
            {
                app_timer_report_map_rsp();
            }
            
            if (g_master_os.os != g_store_os)
            {
                g_store_os = g_master_os.os;
                flash_page_erase(OS_STORE_OFFSET);
                flash_write(OS_STORE_OFFSET, (uint32_t *)&g_store_os, 64);
            }
        } break;
        
        // nothing
        case STEP_NEXT:
        default :
        {
        } break;
    }
}

bool os_judge_done(void)
{
    return (os_judge_env.step == STEP_NONE);
}

APP_MSG_HANDLER(gatt_cmp_evt)
{
    DEBUG("Cmp_evt(op:%d,sta:0x%02x)", param->operation, param->status);
    DEBUG("os:%d, %d",os_judge_env.os_type, g_master_os.os);
    if ((GATT_DISC_BY_UUID_SVC == param->operation) && (param->status == ATT_ERR_ATTRIBUTE_NOT_FOUND))
    {
        os_judge_env.step = STEP_DONE;
    }
}

APP_MSG_HANDLER(gatt_mtu_changed_ind)
{
    DEBUG("mtu_chg:%d,seq:%d", param->mtu, param->seq_num);
    gapc_update_dle(app_env.curidx,LE_MAX_OCTETS,LE_MAX_TIME);
    
    os_judge_env.mtu = 1;
}

APP_MSG_HANDLER(gatt_disc_svc_ind)
{
    DEBUG("disc_svc(shdl:0x%X,ehdl:0x%X,ulen:%d)", param->start_hdl, param->end_hdl, param->uuid_len);
    debugHex(param->uuid, param->uuid_len);
    
    if (0 == memcmp(apple_vendor_uuid, param->uuid, param->uuid_len))
    {
        os_judge_env.os_type = SYS_IOS;
    }
    os_judge_env.step = STEP_DONE;
}

APP_MSG_HANDLER(gatt_disc_svc_incl_ind)
{
    DEBUG("disc_incl(ahdl:0x%X,shdl:0x%X,ehdl:0x%X,ulen:%d)", param->attr_hdl, param->start_hdl, param->end_hdl, param->uuid_len);
    debugHex(param->uuid, param->uuid_len);
}

APP_MSG_HANDLER(gatt_disc_char_ind)
{
    DEBUG("disc_char(ahdl:0x%X,phdl:0x%X,prop:0x%X,ulen:%d)", param->attr_hdl, param->pointer_hdl, param->prop, param->uuid_len);
    debugHex(param->uuid, param->uuid_len);
}

APP_MSG_HANDLER(gatt_disc_char_desc_ind)
{
    DEBUG("disc_desc(ahdl:0x%X,ulen:%d)", param->attr_hdl, param->uuid_len);
    debugHex(param->uuid, param->uuid_len);
}

APP_MSG_HANDLER(gatt_read_ind)
{
    DEBUG("Read_ind(hdl:0x%02x,oft:%d,len:%d)", param->handle, param->offset, param->length);
    debugHex(param->value, param->length);
}

APP_MSG_HANDLER(gatt_event_ind)
{
    DEBUG("Evt_ind(typ:%d,hdl:0x%02x,len:%d)", param->type, param->handle, param->length);
    debugHex(param->value, param->length);
}

APP_MSG_HANDLER(gatt_event_req_ind)
{
    uint8_t conidx = TASK_IDX(src_id);
    
    DEBUG("Evt_req_ind(typ:%d,hdl:0x%02x,len:%d)", param->type, param->handle, param->length);
    debugHex(param->value, param->length);

    gatt_evt_cfm(conidx, param->handle);
}

/**
 ****************************************************************************************
 * @brief SubTask Handler of GATT Message.
 ****************************************************************************************
 */
APP_SUBTASK_HANDLER(gatt_msg)
{
    switch (msgid)
    {
        case GATT_CMP_EVT:
        {
            APP_MSG_FUNCTION(gatt_cmp_evt);
        } break;
        
        case GATT_MTU_CHANGED_IND:
        {
            APP_MSG_FUNCTION(gatt_mtu_changed_ind);
        } break;
        
        case GATT_DISC_SVC_IND:
        {
            APP_MSG_FUNCTION(gatt_disc_svc_ind);
        } break;
        
        case GATT_DISC_SVC_INCL_IND:
        {
            APP_MSG_FUNCTION(gatt_disc_svc_incl_ind);
        } break;
        
        case GATT_DISC_CHAR_IND:
        {
            APP_MSG_FUNCTION(gatt_disc_char_ind);
        } break;
        
        case GATT_DISC_CHAR_DESC_IND:
        {
            APP_MSG_FUNCTION(gatt_disc_char_desc_ind);
        } break;
        
        case GATT_READ_IND:
        {
            APP_MSG_FUNCTION(gatt_read_ind);
        } break;
        
        case GATT_EVENT_IND:
        {
            APP_MSG_FUNCTION(gatt_event_ind);
        } break;
        
        case GATT_EVENT_REQ_IND:
        {
            APP_MSG_FUNCTION(gatt_event_req_ind);
        } break;
        
        default:
        {
            DEBUG("Unknow MsgId:0x%X", msgid);
        } break;
    }

    return (MSG_STATUS_FREE);
}

#endif //(GATT_CLI)
